package edu.qhst.chat.netty.cmdhandler;

import edu.qhst.chat.utils.PackageUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 指令处理器工厂
 *
 * @author 加浓美式
 * @Date 2023/7/5
 */
@Slf4j
public final class CmdHandlerFactory {

    private static final Map<Integer, ICmdHandler> _handlerMap = new HashMap<>();

    /**
     * 私有化类默认构造器
     */
    private CmdHandlerFactory() {
    }

    /**
     * 初始化
     */
    static public void init() throws IllegalAccessException {
        log.info("==== 完成 Code 和 Handler 的关联 ====");

        // 拿出所有实现ICmdHandler的子类
        Set<Class<?>> clazzes = PackageUtil.listSubClazz(
                CmdHandlerFactory.class.getPackage().getName(),
                true,
                ICmdHandler.class);

        for (Class<?> clazz : clazzes) {
            if ((clazz.getModifiers() & Modifier.ABSTRACT) != 0) {
                // 如果是抽象类,
                continue;
            }

            //  获取消息类型
            Integer msgType = 0;
            // 获取类中声明的所有常量
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                if (field.getType().isPrimitive() && java.lang.reflect.Modifier.isFinal(field.getModifiers())) {
                    // 设置可访问私有字段
                    field.setAccessible(true);

                    // 输出常量名和值
                    Object value = field.get(null);
                    if(field.getName().equals("code")) msgType = (Integer) value;
                    System.out.println("Constant: " + field.getName() + ", Value: " + value);
                }
            }

            if (0 >= msgType) {
                continue;
            }

            try {
                ICmdHandler newHandler = (ICmdHandler) clazz.getConstructor().newInstance();

                log.info(
                        "关联 {} <==> {}",
                        msgType,
                        clazz.getName()
                );
                _handlerMap.put(msgType, newHandler);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 创建指令处理器工厂
     *
     * @param code 消息编号
     * @return
     */
    static public ICmdHandler create(Integer code) {
        if (null == code) {
            return null;
        }

        return _handlerMap.get(code);
    }

}
